import React, { Component } from 'react';
import cx from 'classnames';

import { throttle } from 'modules/RX';

import Util from '../../main/util';
import sliderCheck from '../sliderCheck';

import CountryCodeList from './countryCodeList/CountryCodeList';
import fangg from './countryCodeList/fangg.json';
import ClickItem from './ClickItem';
import OneClick from './OneClick';
import Tip from './Tip';

import S from './index.m.less';

/**
 * 调用顺序为：
 * 1、普通短信绑定流程 telephoneVerifyUrl ->  sendCode -> codeVerifyUrl1
 * 2、一键或极验绑定流程  telephoneVerifyUrl -> codeVerifyUrl1
 */

const API = Util.handleApi({
    sendCode: '/v1.0/telephone/', // 发送验证码
    codeVerifyUrl: '/v1.0/telephone/to-update-tel-l', // 验证短信验证码
    codeVerifyUrl1: '/v1.0/bind/tel-bind-l', // 绑定手机号
    telephoneVerifyUrl: '/v1.0/bind/tel-verify-l', // 验证手机号是否可用
});

//为保证之前API请求正常使用，在不改变原API的前提下，此处添加Promise化的请求
const Request = Util.request({
    telephoneVerifyUrl: '/v1.0/bind/tel-verify-l', // 验证手机号是否可用
});

export default async function handleUserTelephone(props = {}) {
    // 这里必须保证绑定走新的接口，验证可以不用管，使用原来的接口
    // 非风险校验模式、非见证宝模式下进行
    if ((!props.riskverify || !props.needSliderCheck) && !props.JZBMethod) {
        // 修改手机号验证接口
        props.telephoneVerifyUrl = API.telephoneVerifyUrl;
        // 修改短信验证接口
        if (/my\/change-sns-right-l/.test(props.codeVerifyUrl)) {
            // 更换头像时做特殊处理
            props.scene = 'changeUserInfo';
        }
        if (/thirdpart\/verify-telephone-return/.test(props.codeVerifyUrl)) {
            // 账单导出时做特殊处理
            props.scene = 'exportBalance';
        }
        // 只有手机号绑定时才更换url，如果为验证，则保持原有逻辑不动
        if (props.type === undefined || props.type === 'bind') {
            props.codeVerifyUrl = API.codeVerifyUrl1;
        }
    }

    // 如果有数字输入框会跟这个组件冲突，需要先把数字输入框给关掉
    document.querySelector('div[class^="fixednumMain--"]') && WPT.Modal.close(false);
    if (props.needSliderCheck) {
        sliderCheck({
            nationCode: '86',
            tel: props.verifyTelephone,
            callback: (obj, res = {}) => {
                WPT.Modal.open(
                    <HandleUserTelephone
                        {...Object.assign(props, {
                            ticket: res.ticket ? res.ticket : '',
                            randstr: res.randstr ? res.randstr : '',
                        })}
                    />,
                    { animationType: 'dd', position: 'bottom', layerClose: !props.cantClose }
                );
            },
        });
        return;
    }
    //只有在APP中，且是绑定的情况下才有一键绑定（一般情况下没有传入手机号都是绑定）
    if (WPT.os.wpt && !props.verifyTelephone) {
        try {
            // 从app中获取手机号，格式为132****9090
            const [phone, data] = await OneClick.getPhone();
            props.extended = false; // 隐藏键盘
            props.tipsText = (
                <Tip url={data?.protocolUrl ?? ''} operator={data?.vendor ?? ''} title={data?.protocolName ?? ''} />
            );
            props.verifyTelephone = phone;
        } catch {
            console.warn('从app中获取手机号失败');
        }
    }

    WPT.Modal.open(<HandleUserTelephone {...props} />, {
        animationType: 'dd',
        position: 'bottom',
        layerClose: !props.cantClose,
    });
}

export const checkTel = (callback, props) => {
    if (!WPT.userinfo.hasTelephone) {
        WPT.handleUserTelephone({
            callback,
            ...props,
        });
        return;
    }
    callback();
};

export class HandleUserTelephone extends Component {
    static defaultProps = {
        title: '请完善你的手机号码信息',
        tipsText: '绑定通过后才能继续操作',
        type: 'bind', // bind 绑定手机号 verify验证手机号
        checkType: ['sms', 'call'], // 发送验证码方式
        telephoneVerifyUrl: API.telephoneVerifyUrl, // 验证电话号码
        sendCodeUrl: API.sendCode, // 发送 验证码
        codeVerifyUrl: API.codeVerifyUrl, // 验证 验证码
        doSomethingFirst: () => {}, // 在 constructor 中先执行
        callback: () => {}, // 验证完后的回调函数
        cancel: () => {}, // 取消回调
        verifyTelephone: '', // 验证时的手机号
        ajaxParam: {},
        serviceTel: '0571-81110039', // 提醒的客服电话
        JZBMethod: {
            switch: false,
            cardType: 'person',
            infoObj: {},
        }, // 见证宝验证模式
        riskverify: false, // 风险校验模式 对应 code 946
        needSliderCheck: false, // 是否需要接入滑动验证, 注意：接入滑动验证必须传入验证的手机号码
        cantClose: false, // 弹窗不能关闭的特殊需求
    };

    constructor(props) {
        super(props);
        props.doSomethingFirst();

        this.state = {
            stepInputCode: props.type !== 'bind',
            verifyTelephoneTime: 59, // 60秒
            secretCode: '', // 验证码
            keyboardNum: [
                { num: 1 },
                { num: 2, letter: 'ABC' },
                { num: 3, letter: 'DEF' },
                { num: 4, letter: 'GHI' },
                { num: 5, letter: 'JKL' },
                { num: 6, letter: 'MNO' },
                { num: 7, letter: 'PQRS' },
                { num: 8, letter: 'TUV' },
                { num: 9, letter: 'WXYZ' },
            ],
            country: 'CN', // 默认中国
            countryCode: '86', // 默认中国区号
            showCountryCode: false, // 是否显示国家区号页面
            sendType: 'sms',
            voiceMethod: false,
            errList: null,
            extended: props.extended ?? true, // 键盘默认展开，在特殊情况下需关闭
            ...this.checkTelVerifyState(props),
        };
    }

    componentDidMount = () => {
        const { checkType, stepInputCode } = this.state;

        // 见证宝第一次进入时不调用发送验证码接口
        this.JZBFirst = true;

        $(window).on('keydown', this.handleKeyInput);
        this.setState(
            {
                sendType: checkType.length === 1 ? checkType[0] : 'sms',
            },
            () => {
                stepInputCode && this.sendCode();
            }
        );
    };

    componentWillUnmount() {
        WPT.Interval.clear('verifyTelephone');
        $(window).off('keydown', this.handleKeyInput);
        if (this.interval) {
            window.clearInterval(this.interval);
            this.interval = null;
        }
    }

    cancel = () => {
        const { cancel } = this.props;
        cancel && cancel();
        WPT.Modal.close(false);
    };

    checkTelVerifyState = (params) => {
        let newParams = { ...params };

        const { verifyTelephone } = newParams;
        // 国际号码，只能使用短信验证
        if (verifyTelephone && verifyTelephone.indexOf('-')) {
            const strTel = verifyTelephone.split('-');
            Object.keys(fangg).some((letter) =>
                fangg[letter].some((i) => {
                    if (i.code === strTel[0]) {
                        newParams = {
                            ...newParams,
                            country: i.abbreviation,
                            countryCode: i.code,
                            pattern: i.pattern,
                            verifyTelephone: strTel[1],
                            checkType: ['sms'],
                            sendType: 'sms',
                        };
                        return true;
                    }
                    return false;
                })
            );
        } else {
            // 国内电话使用传递进来的验证方式
            newParams.checkType = this.props.checkType;
            newParams.sendType = this.props.checkTypeObj;
        }

        // 获取验证码类型默认为[sms, call]的第一个元素，如果不在数组内，取第一个
        if (!newParams.checkType.includes(newParams.sendType)) {
            newParams.sendType = newParams.checkType[0]; // eslint-disable-line
        }

        // 如果手机号不存在，那么将手机号置为空字符串，因为有时候外面传进来的手机号可能为null
        newParams.verifyTelephone = newParams.verifyTelephone || '';

        return newParams;
    };

    setShowCountrycodeList = (value = true) => {
        // 如果是一键登录模式，不允许修改国家
        if (OneClick.canUseOneClickInfo(this.state.verifyTelephone)) return;
        // 控制显示“选择国家”组件
        this.setState({ showCountryCode: value });
    };

    setCountryInfo = (country, countryCode) => {
        // 选择区号组件的回调函数
        this.setState({
            checkType: country !== 'CN' ? ['sms'] : this.props.checkType,
            country,
            countryCode,
        });
    };

    // 国内手机号格式化 // 从选择区号页面返回时调用
    formatVerifyTelephone = () => {};

    handleKeyInput = (e) => {
        if (e.keyCode == '8') {
            // Backspace  delete
            this.delete();
        }
        if (e.keyCode >= 48 && e.keyCode <= 57) {
            this.input(e.keyCode - 48);
        }
        if (e.keyCode >= 96 && e.keyCode <= 105) {
            this.input(e.keyCode - 96);
        }
        if (e.keyCode == 190) {
            this.input('.');
        }
    };

    // 输入
    input = (num) => {
        const { stepInputCode, secretCode, verifyTelephone } = this.state;

        if (!stepInputCode) {
            const formatTelephone = this.format(`${verifyTelephone}${num}`);
            this.setState({
                verifyTelephone: formatTelephone,
            });
        } else {
            const formatSecretCode = this.format(`${secretCode}${num}`);
            this.setState({
                secretCode: formatSecretCode,
            });
        }
    };

    format = (num) => {
        const { JZBMethod } = this.props;
        if (JZBMethod.switch && JZBMethod.cardType === 'enterprise') {
            num = num.replace(/[^\d.]/g, ''); // 清除“数字”和“.”以外的字符
            num = num.replace(/\.{2,}/g, '.'); // 只保留第一个. 清除多余的
            num = num.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
            // eslint-disable-next-line no-useless-escape
            num = num.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3'); // 只能输入两个小数
            if (num.indexOf('.') < 0 && num != '') {
                // 以上已经过滤，此处控制的是如果没有小数点，首位不能为类似于 01、02的金额
                num = parseFloat(num);
                num = String(num);
            }
        } else {
            num = num.replace(/[\D]/g, ''); // 只能为数字
        }

        if (!this.state.stepInputCode) {
            if (this.state.country === 'CN') {
                // 中国手机号码
                num = num.slice(0, 11);
            } else {
                num = num.slice(0, 20);
            }
        } else {
            // todo JZB中 num 几位
            // eslint-disable-next-line no-lonely-if
            if (JZBMethod.switch) {
                if (JZBMethod.cardType === 'person') {
                    num = num.substr(0, 6);
                } else {
                    num = num.substr(0, 5);
                }
            } else {
                num = num.substr(0, 4);
            }
        }
        return num;
    };

    delete = () => {
        const { stepInputCode, verifyTelephone, secretCode } = this.state;

        if (!stepInputCode) {
            const formatTelephone = this.format(verifyTelephone.substr(0, verifyTelephone.length - 1));
            this.setState({
                verifyTelephone: formatTelephone,
            });
        } else {
            const formatSecretCode = this.format(secretCode.substr(0, secretCode.length - 1));
            this.setState({
                secretCode: formatSecretCode,
            });
        }
    };

    handleTelChange = (e) => {
        this.setState({
            verifyTelephone: e.target.value,
        });
    };

    telShowFormat = () => {
        const { country, verifyTelephone } = this.state;
        if (country === 'CN' && !!verifyTelephone) {
            if (verifyTelephone.length >= 4 && verifyTelephone.length < 8) {
                return `${verifyTelephone.slice(0, 3)}-${verifyTelephone.slice(3, 7)}`;
            }
            if (verifyTelephone.length >= 8) {
                return `${verifyTelephone.slice(0, 3)}-${verifyTelephone.slice(3, 7)}-${verifyTelephone.slice(7, 11)}`;
            }
            return verifyTelephone;
        }
        return verifyTelephone || '';
    };

    inputClear = () => {
        // 如果是一键登录模式，则将提示恢复到默认显示
        if (OneClick.canUseOneClickInfo(this.state.verifyTelephone)) {
            this.setState({
                tipsText: HandleUserTelephone.defaultProps.tipsText,
            });
        }
        const { stepInputCode } = this.state;
        stepInputCode
            ? this.setState({
                  secretCode: '',
              })
            : this.setState({
                  verifyTelephone: '',
              });
        // 执行清空操作后，如果键盘没有弹起，则需显示键盘
        if (this.state.extended !== true) {
            this.setState({
                extended: true,
            });
        }
    };

    //通过token进行手机号验证,这是因为此时无法获取用户完整手机号
    verifyPhoneWithToken = (token) => {
        const { countryCode, verifyTelephone } = this.state;
        return Request.telephoneVerifyUrl.post(
            {
                nationCode: countryCode,
                tel: verifyTelephone,
                accessToken: token,
                verifyType: this.getVerifyType(),
            },
            { handleCommonError: false }
        );
    };
    //工具方法，生成网络请求中参数verifyType的值
    getVerifyType = () => {
        const { verifyTelephone } = this.state;
        if (OneClick.canUseOneClickInfo(verifyTelephone)) {
            return 'oneClick';
        }
        if (OneClick.isLocalVerify(verifyTelephone)) {
            return 'oneClickVerify';
        }
        return 'code';
    };

    next = async () => {
        const { verifyTelephone, countryCode } = this.state;
        const { telephoneVerifyUrl, ajaxParam } = this.props;
        if (!verifyTelephone) return;
        // 执行一键登录的逻辑
        if (OneClick.canUseOneClickInfo(verifyTelephone)) {
            // 如果是一键登录的绑定，为不影响原有逻辑，故手动将验证码置为8888，方便后续逻辑继续执行
            // eslint-disable-next-line
            this.state.secretCode = '8888';
            try {
                //从app中获取一键绑定所需token
                const res = await OneClick.getToken().then(this.verifyPhoneWithToken);
                if (res.code === 0) {
                    if (res.data) {
                        await this.handleVerifyPhoneResult(res.data, this.confirm);
                    } else {
                        WPT.Modal.tips('数据出错');
                    }
                } else {
                    WPT.Modal.tips(res.msg);
                }
            } catch (e) {
                console.warn('从app获取token失败', e);
                WPT.Modal.tips('验证出错，请手动输入手机号重试');
                // 一键绑定失败后，重置状态，变为用户手动输入界面， 此处通过模拟用户点击x号执行逻辑
                this.inputClear();
            }
            return;
        }
        // 执行本机号码校验的逻辑
        if (OneClick.isLocalVerify(verifyTelephone)) {
            // eslint-disable-next-line
            this.state.secretCode = '8888';
            try {
                const res = await OneClick.getLocalPhoneToken().then(this.verifyPhoneWithToken);
                if (res.code === 0) {
                    if (res.data) {
                        await this.handleVerifyPhoneResult(res.data, this.confirm);
                    } else {
                        WPT.Modal.tips('数据出错');
                    }
                    return;
                }
            } catch (e) {
                console.warn('从app获取本机号码校验token失败', e);
                //极验获取token失败之后，将本机号码删掉
                OneClick.phone = '';
            }
        }
        const params = {
            ...ajaxParam,
            tel: verifyTelephone,
            nationCode: countryCode,
        };
        WPT.postData(telephoneVerifyUrl, params, (res) => {
            if (res.code === 0) {
                if (res.data) {
                    this.handleVerifyPhoneResult(res.data, this.sendCode);
                } else {
                    WPT.Modal.tips('数据出错');
                }
            } else {
                WPT.Modal.tips(res.msg);
            }
        });
    };

    handleVerifyPhoneResult = async (data, completion) => {
        const { handleVerifyResult, VerifyType } = await import(
            /* webpackPrefetch: true */ /* webpackChunkName: "util" */ '../../views/my/accountMerge/utils'
        );
        handleVerifyResult({
            data,
            type: VerifyType.phone,
            completion,
        });
    };

    sendCodeCallback = (realCheckType) => {
        const { JZBMethod } = this.props;
        this.setState(
            {
                stepInputCode: true,
                tipsText: JZBMethod.cardType == 'person' ? '收不到验证码' : '收不到短信',
                title:
                    realCheckType === 'call'
                        ? `语音电话将拨打至 ${this.telShowFormat()}`
                        : (() => {
                              if (JZBMethod.switch) {
                                  return JZBMethod.cardType == 'person'
                                      ? `接收验证码手机号 ${this.telShowFormat()}`
                                      : `接收短信手机号 ${this.telShowFormat()}`;
                              }
                              return `验证码已发送至 ${this.telShowFormat()}`;
                          })(),
                voiceMethod: realCheckType === 'call',
                verifyTelephoneTime: 59,
                secretCode: '',
            },
            () => {
                this.resetCountDown();
            }
        );
    };

    JZBSendCode = (realCheckType) => {
        const { sendCodeUrl, JZBMethod } = this.props;

        if (this.JZBFirst) {
            this.sendCodeCallback(realCheckType);
            this.JZBFirst = false;
            return;
        }

        WPT.getData(
            sendCodeUrl,
            {
                bankId: JZBMethod.infoObj.bankId,
            },
            (res) => {
                this.sendCodeCallback(realCheckType);
                if (res.code != 0 || !res.data.isNeedBind) {
                    if (res.code == 139 || res.code == 90009) {
                        WPT.Modal.alert(res.msg, () => {
                            WPT.Modal.close(false);
                        });
                    } else if (res.code == 0 && !res.data.isNeedBind) {
                        WPT.Modal.tips(res.data.msg || '验证码发送失败');
                    } else {
                        WPT.Modal.tips(res.msg || '验证码发送失败');
                    }
                }
            }
        );
    };

    sendCode = () => {
        const { verifyTelephone, countryCode, sendType } = this.state;
        const { sendCodeUrl, type, JZBMethod, riskverify, needSliderCheck, ticket, randstr } = this.props;
        let realCheckType = sendType;

        if (riskverify) {
            WPT.getData(sendCodeUrl, {}, (res) => {
                this.sendCodeCallback(realCheckType);
                if (res.code != 0) {
                    WPT.Modal.tips(res.msg);
                }
            });
            return;
        }

        if (countryCode !== '86') {
            realCheckType = 'sms';
        }
        if (JZBMethod.switch) {
            this.JZBSendCode(realCheckType);
            return;
        }

        // 对账单页面下发送验证码接口改为接入图形验证码的接口
        if (needSliderCheck) {
            WPT.getData(
                sendCodeUrl,
                {
                    telephone: verifyTelephone,
                    nationCode: countryCode,
                    type: realCheckType,
                    ticket,
                    randstr,
                    tg: 1,
                },
                (res) => {
                    if (res.code === 0) {
                        this.sendCodeCallback(realCheckType);
                    } else if (res.code === 1000) {
                        WPT.Modal.tips(`${res.msg}60秒后请重新再试`);
                    } else {
                        type === 'verify' && this.sendCodeCallback(realCheckType);
                        WPT.Modal.tips(res.msg);
                    }
                }
            );
            return;
        }

        WPT.getData(
            sendCodeUrl + realCheckType,
            {
                tel: verifyTelephone,
                nationCode: countryCode,
                type: realCheckType,
            },
            (res) => {
                if (res.code === 0) {
                    this.sendCodeCallback(realCheckType);
                } else if (res.code === 1000) {
                    WPT.Modal.tips(`${res.msg}60秒后请重新再试`);
                } else {
                    type === 'verify' && this.sendCodeCallback(realCheckType);
                    WPT.Modal.tips(res.msg);
                }
            }
        );
    };

    renderTelInput = () => {
        const { cantClose } = this.props;
        const { country, countryCode, verifyTelephone, title, tipsText, stepInputCode, extended } = this.state;

        return (
            <div className={cx(S.controlContainer, stepInputCode && S.hide)}>
                {!cantClose && <div className={S.close} onClick={this.cancel} />}
                <div className={S.title}>{title}</div>
                <div className={S.inputContainer}>
                    <span className={S.countryCode} onClick={this.setShowCountrycodeList}>
                        {`${country} + ${countryCode}`}
                    </span>
                    <div className={cx(S.telInput, !extended ? '' : verifyTelephone ? S.hasInput : S.noInput)}>
                        {OneClick.canUseOneClickInfo(verifyTelephone) ? verifyTelephone : this.telShowFormat()}
                    </div>
                    {verifyTelephone && <span className={S.clear} onClick={this.inputClear} />}
                </div>
                <div
                    className={cx(S.next, verifyTelephone ? S.enabled : '')}
                    data-touch="touchEffect"
                    onClick={throttle(this.next, 1000)}
                >
                    立即绑定
                </div>
                <div className={S.remind}>{tipsText}</div>
            </div>
        );
    };

    resetCountDown = () => {
        const { verifyTelephoneTime } = this.state;
        if (!this.interval && verifyTelephoneTime !== 0) {
            this.interval = setInterval(() => {
                this.setState(
                    {
                        verifyTelephoneTime: this.state.verifyTelephoneTime - 1,
                    },
                    () => {
                        if (this.state.verifyTelephoneTime === 0) {
                            window.clearInterval(this.interval);
                            this.interval = null;
                        }
                    }
                );
            }, 1000);
        }
    };

    renderImpAlertNode = () => {
        const { riskverify } = this.state;
        const { serviceTel } = this.props;
        return (
            <div className={S.modalContainer}>
                <div className={S.title}>收不到验证码</div>
                <div className={S.content}>
                    {!riskverify ? (
                        <>
                            <div>
                                1.请联系{' '}
                                <a className={S.highlight} href={`tel:${serviceTel}`}>
                                    {serviceTel}
                                </a>{' '}
                                进行人工验证；
                            </div>
                            <div>2.检查手机是否启用了短信/电话拦截。</div>
                        </>
                    ) : (
                        <>
                            <div>1.请检查语音是否被手机安全软件拦截；</div>
                            <div>
                                2.获取更多帮助，请拨打客服电话
                                <br />
                                <a className={S.highlight} href={`tel:${serviceTel}`}>
                                    {serviceTel}
                                </a>
                                。
                            </div>
                        </>
                    )}
                </div>
            </div>
        );
    };

    renderJZBImpAlertNode = () => {
        const { serviceTel, JZBMethod } = this.props;
        return (
            <div
                className={cx(
                    S.modalContainer,
                    JZBMethod.cardType === 'person' ? S.JZBModalPerson : S.JZBModalEnterprise
                )}
            >
                <div className={S.title}>收不到验证码</div>
                <div className={S.content}>
                    <div>1.请联系确认当前是否使用银行预留手机号；</div>
                    <div>2.请检查短信是否被手机安全软件拦截；</div>
                    <div>3.若预留手机号已停用，请联系银行客服咨询；</div>
                    {JZBMethod.cardType === 'enterprise' && (
                        <div>4.若未开通银行短信服务，请查看最新银行汇款记录或联系银行客服咨询；</div>
                    )}
                    <div>
                        {JZBMethod.cardType === 'enterprise' ? '5' : '4'}
                        .获取更多帮助，请拨打客服电话
                        <a className={S.highlight} href={`tel:${serviceTel}`}>
                            {serviceTel}
                        </a>
                        。
                    </div>
                </div>
            </div>
        );
    };

    cantGetCode = () => {
        const { JZBMethod } = this.props;
        const renderImpAlertComponent = JZBMethod.switch ? this.renderJZBImpAlertNode : this.renderImpAlertNode;
        WPT.Modal.impAlert(renderImpAlertComponent(), {
            btnList: [
                {
                    btnName: '我知道了',
                    callback: () => {
                        WPT.Modal.close();
                    },
                    className: S.knowBtn,
                },
            ],
        });
    };

    resend = (sendType) => {
        this.setState(
            {
                sendType,
            },
            () => {
                this.sendCode();
            }
        );
    };

    JZBConfirm = () => {
        const { JZBMethod, codeVerifyUrl, callback } = this.props;
        const { secretCode } = this.state;
        if (secretCode.length === 0) return;
        let realSecretCode = secretCode;
        if (secretCode[secretCode.length - 1] == '.') {
            realSecretCode = secretCode.slice(0, secretCode.length - 1);
        }
        WPT.getData(
            codeVerifyUrl,
            {
                bankId: JZBMethod.infoObj.bankId,
                code: realSecretCode,
            },
            (res) => {
                callback && callback(res);
            }
        );
    };

    confirm = () => {
        const { verifyTelephone, secretCode, countryCode, sendType } = this.state;
        const { type, codeVerifyUrl, callback, JZBMethod, riskverify } = this.props;

        if (secretCode.length === 0) return;

        if (riskverify) {
            WPT.postData(
                codeVerifyUrl,
                {
                    verifyType: sendType,
                    callCode: secretCode,
                },
                (res) => {
                    if (res.code == 0) {
                        callback && callback();
                        WPT.Modal.close(false);
                    } else {
                        WPT.Modal.tips(res.msg);
                    }
                }
            );
            return;
        }

        if (JZBMethod.switch) {
            if (JZBMethod.cardType === 'enterprise') {
                WPT.Modal.infoTip(
                    <div className={S.infoTip}>
                        <div className={S.title}>温馨提示</div>
                        <p>
                            请将平安银行汇入您对公账户的金额填入框中，完成验证后即可正常提现。
                            如未收到短信，请前往银行查询入账流水，切勿错填为提现金额！
                        </p>
                    </div>,
                    {
                        btnList: [
                            {
                                btnName: '取消',
                                className: S.cancelBtn,
                            },
                            {
                                btnName: '继续验证',
                                className: S.continueBtn,
                                callback: this.JZBConfirm,
                            },
                        ],
                        needPadding: true,
                    }
                );
                return;
            }
            this.JZBConfirm();
            return;
        }

        // 测试反馈接口请求时间可能超过 1 秒，所以根据接口返回来控制节流
        if (this.confirmRequsting) return;
        this.confirmRequsting = true;
        WPT.postData(
            codeVerifyUrl,
            {
                tel: verifyTelephone,
                code: secretCode,
                nationCode: countryCode,
                checkTelephone: type === 'bind' ? 0 : 1, // type=bind更新绑定手机号，否则为语音验证手机号
                scene: this.props.scene,
                verifyType: this.getVerifyType(),
            },
            async (res) => {
                if (res.code === 0) {
                    if (res.data && res.data.errorList) {
                        this.setState({
                            errList: res.data.errorList,
                        });
                        return;
                    }
                    // 电话验证通过
                    WPT.userinfo.hasTelephone = 88888888888;
                    WPT.userinfo.isSubscribe = 2;
                    if (type === 'bind') {
                        await new Promise((resolve) => {
                            WPT.Modal.success('绑定成功', {
                                callback: resolve,
                                time: 1000,
                            });
                        });
                    }
                    if (res.data && res.data.userinfo) WPT.wptBridge.bindTelCallAPP(res.data.userinfo);
                    WPT.Modal.close(false);
                    callback(countryCode != '86' ? `${countryCode}-${verifyTelephone}` : verifyTelephone, res);
                } else {
                    WPT.Modal.tips(res.msg);
                }
                this.confirmRequsting = false;
            }
        );
    };

    renderSendButton = () => {
        const { checkType } = this.state;
        if (checkType.length === 1) {
            return checkType[0] === 'sms' ? (
                <span className={S.bgcBtn} onClick={() => this.resend('sms')}>
                    短信验证
                </span>
            ) : (
                <span className={S.bgcBtn} onClick={() => this.resend('call')}>
                    语音验证
                </span>
            );
        }
        return (
            <div>
                <span className={S.borderBtn} onClick={() => this.resend('call')}>
                    语音验证
                </span>
                <span className={S.bgcBtn} onClick={() => this.resend('sms')}>
                    短信验证
                </span>
            </div>
        );
    };

    renderCodeInput = () => {
        const { secretCode, verifyTelephoneTime, title, tipsText, voiceMethod, stepInputCode, riskverify } = this.state;
        const { JZBMethod, cantClose } = this.props;

        return (
            <div
                className={cx(
                    S.stepControlContainer,
                    voiceMethod ? S.voiceMethodContainer : '',
                    JZBMethod.switch ? S.JZBContainer : '',
                    riskverify ? S.riskverifyContainer : '',
                    !stepInputCode && S.hide
                )}
            >
                {!cantClose && <div className={S.close} onClick={this.cancel} />}
                <div className={S.title}>{title}</div>
                {voiceMethod && !JZBMethod.switch && (
                    <div className={S.voiceRemind}>请注意接听 0755/0578 等开头的来电</div>
                )}
                <div className={cx(S.inputContainer, voiceMethod ? S.voiceMethodInput : '')}>
                    <div style={{ display: 'flex' }}>
                        {JZBMethod.cardType === 'enterprise' && <div className={S.JZBInputTitle}>汇入金额</div>}
                        <div
                            className={cx(
                                S.codeInput,
                                JZBMethod.cardType === 'person' ? '' : S.JZBEnterprise,
                                secretCode ? S.hasInput : S.noInput
                            )}
                        >
                            {secretCode}
                        </div>
                    </div>
                    {JZBMethod.cardType === 'person' ? (
                        <div className={S.rightContainer}>
                            {secretCode && <div className={S.clear} onClick={this.inputClear} />}
                            {verifyTelephoneTime !== 0 ? (
                                <div className={S.countDown}>{verifyTelephoneTime}s 后重新获取</div>
                            ) : (
                                this.renderSendButton()
                            )}
                        </div>
                    ) : (
                        secretCode && (
                            <div className={S.rightContainer}>
                                <div className={S.clear} onClick={this.inputClear} />
                            </div>
                        )
                    )}
                </div>
                <div className={S.remind} onClick={this.cantGetCode}>
                    {tipsText}
                </div>
                <div
                    className={cx(S.confirm, secretCode ? S.enabled : '')}
                    data-touch="touchEffect"
                    onClick={throttle(this.confirm, 1000)}
                >
                    {JZBMethod.cardType === 'person' ? '确定' : '下一步'}
                </div>
                {riskverify && <div className={S.JZBTips}>验证通过后才能继续操作</div>}
                {JZBMethod.switch && (
                    <div className={S.JZBTips}>
                        {JZBMethod.cardType === 'person'
                            ? '验证通过后才能继续操作'
                            : '将平安银行汇入的金额填入框中，完成验证即可提现'}
                    </div>
                )}
            </div>
        );
    };

    renderErrList = () => {
        const { errList, verifyTelephone } = this.state;
        return (
            <div className={S.errBox}>
                <div className={S.errTitle}>
                    <span>当前账户已存在以下数据</span>
                    <br />
                    <span>{`暂时不能与 ${verifyTelephone} 绑定`}</span>
                </div>
                <div className={cx(S.errContent, errList.length === 1 ? S.onlyOneItem : '')}>
                    {!$.isEmptyObject(errList) &&
                        errList.map((errItem, i) => (
                            <div key={i} className={cx(S.errItem, errList.length === 1 ? S.onlyOneItem : '')}>
                                <div className={S.itemTitle}>
                                    <div className={cx(S.wptFM, S[`${errItem.icon}`])} />
                                    <span>{errItem.name}</span>
                                </div>
                                <div className={S.itemContent}>{errItem.value}</div>
                            </div>
                        ))}
                </div>
                <div className={S.brBgc} />
                <div className={S.errButton} {...WPT.onTouchEnd(this.cancel, 0)}>
                    我知道了
                </div>
            </div>
        );
    };

    render() {
        const { showCountryCode, keyboardNum, errList, extended } = this.state;
        const { JZBMethod } = this.props;
        return $.isEmptyObject(errList) ? (
            <div className={S.bindTelephoneContainer}>
                {showCountryCode && (
                    <CountryCodeList
                        setCountryInfo={this.setCountryInfo}
                        setShowCountrycodeList={this.setShowCountrycodeList}
                        formatVerifyTelephone={this.formatVerifyTelephone}
                    />
                )}
                {/* {stepInputCode ? this.renderCodeInput() : this.renderTelInput()} */}
                {this.renderTelInput()}
                {this.renderCodeInput()}
                <div className={cx(S.keyboard, extended ? '' : S.fold)}>
                    <div
                        className={S.numkey}
                        onContextMenu={(e) => {
                            e.preventDefault();
                        }}
                    >
                        <ul>
                            {keyboardNum.map((item) => (
                                <ClickItem
                                    key={item.num}
                                    data-touch="touchEffect"
                                    className={S.num}
                                    onClick={() => this.input(item.num)}
                                >
                                    <div className={S.num}>{item.num}</div>
                                    <div className={S.letter}>{item.letter}</div>
                                </ClickItem>
                            ))}
                            {JZBMethod.cardType === 'person' ? (
                                <ClickItem
                                    data-touch="touchEffect"
                                    className={cx(S.num, S.othernum)}
                                    onClick={this.cancel}
                                >
                                    取消
                                </ClickItem>
                            ) : (
                                <ClickItem
                                    data-touch="touchEffect"
                                    className={S.num}
                                    style={{ lineHeight: '50px' }}
                                    onClick={() => this.input('.')}
                                >
                                    .
                                </ClickItem>
                            )}
                            <ClickItem
                                data-touch="touchEffect"
                                className={S.num}
                                style={{ lineHeight: '50px' }}
                                onClick={() => this.input(0)}
                            >
                                0
                            </ClickItem>
                            <ClickItem data-touch="touchEffect" className={S.delete} onClick={this.delete} />
                        </ul>
                    </div>
                </div>
            </div>
        ) : (
            this.renderErrList()
        );
    }
}
